﻿using System;
using System.Data.SqlClient;

using Fuse8.DomainFramework.Domain;
using Fuse8.DomainFramework.Common;

namespace Fuse8.DomainFramework.DataAccess.SqlDatabase
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class HttpContextSqlUnitOfWorkFactory<T> : HttpContextUnitOfWorkFactory<T>
        where T : class, IEntityObject, new()
    {
        /// <summary>
        /// 
        /// </summary>
        public string ConnectionString { get; set; }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        public HttpContextSqlUnitOfWorkFactory(string connectionString)
        {
            ConnectionString = connectionString;
        }

        #region HttpContextUnitOfWorkFactory override

        /// <summary>
        /// 
        /// </summary>
        protected override string FactoryKeyFormat
        {
            get
            {
                return "HttpContextSqlUnitOfWorkFactory_{0}";
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="withTransaction"></param>
        /// <returns></returns>
        public override IUnitOfWork<T> Create(bool withTransaction)
        {
            var connection = SqlConnectionFactoryWrapper.GetOrCreateConnection(CurrentHttpContext, ConnectionString, withTransaction);

            var result = new SqlUnitOfWork<T>
            {
                Connection = connection
            };

            if (withTransaction)
            {
                result.Transaction = connection.BeginTransaction();
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TMain"></typeparam>
        /// <param name="unitOfWork"></param>
        /// <returns></returns>
        public override IUnitOfWork<T> CreateFrom<TMain>(IUnitOfWork<TMain> unitOfWork)
        {
            Guard.ArgumentNotNull(unitOfWork, "unitOfWork");

            var dbUnitOfWork = unitOfWork as IDbUnitOfWork;
            if (dbUnitOfWork == null)
            {
                throw new NotSupportedException("Unit of work doesn't support db connections");
            }

            if (dbUnitOfWork.Transaction == null)
            {
                throw new NotSupportedException("Db transaction is required");
            }

            return new SqlUnitOfWork<T>
            {
                Connection = dbUnitOfWork.Connection,
                Transaction = dbUnitOfWork.Transaction
            };
        }

        /// <summary>
        /// 
        /// </summary>
        public override void CommitTransaction()
        {
            var sqlUnitOfWork = Get(true) as SqlUnitOfWork<T>;

            if (sqlUnitOfWork != null)
            {
                var transaction = sqlUnitOfWork.Transaction;

                if (transaction != null)
                {
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override void RollbackTransaction()
        {
            var sqlUnitOfWork = Get(true) as SqlUnitOfWork<T>;

            if (sqlUnitOfWork != null)
            {
                var transaction = sqlUnitOfWork.Transaction;

                if (transaction != null)
                {
                    transaction.Rollback();
                }
            }
        }

        #endregion
    }
}
